vercel private submodule 배포 시 인증문제 해결방법
문제 인식
git submodule이 포함된 nextJS 프로젝트를 vercel로 배포하던 중 다음과 같은 빌드 에러를 발견했다.

에러 메시지를 살펴보면 clone을 실패했다고 나오는데, 그도 그럴 것이 private repository이기 때문에 vercel은 github 인증정보가 없어서 클론에 실패한 것이다.
vercel은 submodule을 클론하려고 먼저 시도한 뒤 build를 실행하려고 한다. 초기 submodule를 불러오는건 항상 실패하기 때문에 이후 build 스크립트를 통해 직접 submodule을 불러와야 한다.
인증은 어떻게?
github의 인증 방식은 매우매우 많다.
- 아이디 비밀번호 입력
- ssh 키 방식
- git credential manager - 키체인
- oauth app - vscode 등
- url 토큰주입 방식
- GITHUB_TOKEN (github action 전용)
이 중 vercel에서 어떤식으로 인증정보를 가져와야 고민해보면,
- 아이디 비번: 직접 터미널로 입력할수가 없음
- ssh 키: vercel 환경이 매번 초기화되기 때문에 매번 ssh 설정파일을 만들어주는게 불편함, 키 관리가 힘듦
- 키체인: 로컬에서 보통 사용하므로 패스
- oath: 못씀
가장 간편한 방식이 url에 인증정보를 직접 추가해주는 방식이다.
사용방법은 https://{토큰}@github.com/... 이런식으로 Repository URL에 토큰을 추가해서 인증할 수 있다.
인증정보 추가
현재 서브모듈 설정은 다음과 같다.
%% .gitmodules %%
[submodule "contents"]
path = contents
url = https://github.com/ka1dyn/obsidian-blog.git
그냥 이 url을 https://{PAT_TOKEN}@github.com/ka1dyn/obsidian-blog.git 처럼 수정하기만 하면 바로 동작한다. 하지만 문제는, 메인 프로젝트 자체는 public이라는 것이다. 인증정보를 직접 삽입하면 모두가 볼 수 있게 되고 키가 노출된다.
방법 1 - 빌드 전 URL 직접 수정
vercel 빌드타임에 url을 직접 수정하는 방식이다.
%% vercel-prebuild.sh %%
# 기존 url 연결 끊기
git submodule deinit -f . || true
rm -rf .git/modules/contents
# 파일 내용 수정
sed -i "s|https://github.com/|https://${GH_TOKEN}@github.com/|g" .gitmodules
# 서브모듈 URL 동기화
git submodule sync --recursive
# 내용 가져오기, 업데이트
git submodule update --init --recursive --remote

vercel에서 빌드하기 전, 미리 vercel-prebuild.sh를 실행시켜 서브모듈 URL을 바꿔준다. 이렇게 하면
vercel에서 기존에 등록되어 있던 일반 URL https://github.com/ka1dyn/obsidian-blog.git의 연결을 끊고, 새로 인증정보가 포함된 URL을 기반으로 새로 클론을 시도한다. 이 때, GH_TOKEN 인증 토큰의 경우에는 미리 vercel에 환경변수로 등록해줘야한다.


로그를 읽어보면 ./vercel-prebuild.sh이 실행되면서 기존 submodule을 unregistered한 뒤, 인증정보가 있는 url로 sync 및 새로 받아오는 것을 확인할 수 있다.
방법 2 - git config을 사용한 url alias
git에서는 특정 url로 요청을 보낼 때 다른 url로 자동으로 변환해주는 기능이 있다.
사용법은 다음과 같다.
$ git config [scope] url."<바꿀 주소>".insteadOf "<원래 주소>"
이를 활용하면 기존에 submodule의 주소로 update요청을 할 때, 자동으로 인증정보가 포함된 주소로 보내도록 강제 전환이 가능하다.
%% vercel-prebuild.sh %%
# URL 강제변환
git config --global url."https://${GH_TOKEN}@github.com/".insteadOf "https://github.com/"
# 동기화
git submodule sync
# trace를 통한 디버깅(url 잘 바뀌었는지 확인), 내용 가져오기
GIT_TRACE=1 git submodule update --init --recursive
vercel 빌드타임에 존재하는 git의 설정을 바꿔주기 위해 git config --global로 url alias를 적용한다. 이 때 반드시 global scope로 해줘야 적용됨을 확인했다. (local 설정으로는 안되는걸 직접 확인해봤음)
이처럼 url을 바꿔주고 trace로 내용을 확인해보면

이런식으로 원격지에 요청 보낼 때 인증정보가 들어감을 확인할 수 있었다.